Skip to content

docs(spec): the major-18 conversions docblock places the import, not the definition - #30643

Merged
objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-29994-conversions-placement-docblock
Nov 5, 2026
Merged

objectstack-fleet[bot] merged 1 commit into
mainfrom
claude/issue-29994-conversions-placement-docblock

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by Sales · project thread

domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P

Fixes #29994
Clause-②: no
Metadata-protocol: none

维护者速读

  • 改了什么:只改 packages/spec/src/conversions/registry.ts 中 MAJOR_18_CONVERSIONS 头注的一条「新增转换」规则,不动任何代码行。
  • 为什么改:转换拆成每条一个模块后,头注仍教作者把定义写进 registry.ts;现改为写独立模块、在 registry.ts 只加 import 与列表项,与合并测试一致。
  • 风险与回滚:纯注释,dist/ 不含这段文字,不发布、零运行时影响;回滚即 revert 本提交。
  • 先看:packages/spec/src/conversions/registry.ts 第 181–189 行(唯一改动的 hunk)。
  • 两分钟验证:pnpm --filter @objectstack/spec exec vitest run --maxWorkers=2 scripts/conversions-major18-merge.test.ts,预期 Tests 12 passed (12)。
  • 需要你做的:无,席位落地。

What changes

One bullet of the MAJOR_18_CONVERSIONS docblock's "To add a conversion" list, the only one the per-entry split (PR #29993) made false. The other two bullets (insert the entry where its identifier sorts; how to pick order), the conflict explanation above them, and the closing pointer to the merge test are still true and unchanged. No code line moves.

Old:

DEFINE it directly above the definition of the entry that follows it in this list, so the conversion defined next after it is that entry. One that sorts last is defined after every other conversion, directly above OrderedConversion. The end of the definitions is one gap too: defining every new conversion there conflicts exactly as appending here did.

New (two bullets):

DEFINE it in a module of its own, ./entries/18/ID.ts, the file named for the conversion's id and exporting it by name (export { IDENTIFIER };). A new file never conflicts.

IMPORT it directly above the import of the entry that follows it in this list, so the conversion imported next after it is that entry. One that sorts last is imported after every other ./entries/18/ import. The imports stand where the definitions stood before the split, and their end is one gap too: importing every new conversion there conflicts exactly as appending here did.

(ID and IDENTIFIER stand for the placeholders the source writes in angle brackets.)

Each sentence is taken from what packages/spec/scripts/conversions-major18-merge.test.ts asserts, not from the card's paraphrase:

  • module path and name: MODULE_PATH (entries/18/ID.ts) and definitionInModule (const IDENTIFIER: MetadataConversion = { with id: 'ID', toMajor: 18, ending export { IDENTIFIER };);
  • import above the successor's import: placementFindings (the import that comes next is the next list entry's);
  • one that sorts last: definitionsTail, after the last ./entries/18/ import (today that is also the last import in the file, directly above OrderedConversion's doc comment, but the test anchors on the import, so the rule does too);
  • the tail is a gap: the lit control "the same two conversions imported after every other conversion conflict".

It matches what .claude/skills/spec-property-retirement/SKILL.md teaches on main after PR #30109 (entries/TOMAJOR/ID.ts, named for the id, exported by name; the import directly above the successor entry's import).

Verification

Head 6943445b89, base 778aedf666.

  • packages/spec/scripts/conversions-major18-merge.test.ts (the authority, unchanged): Test Files 1 passed (1), Tests 12 passed (12).
  • pnpm --filter @objectstack/spec build && pnpm --filter @objectstack/spec check:generated: lock VERDICT command-exit 0; "All 14 generated artifacts are up to date".
  • eslint --no-inline-config packages/spec/src/conversions/registry.ts: exit 0.
  • pnpm check:doc-authoring: exit 0.
  • Changeset: none, skip-changeset. A comment on a non-exported const; measured after the build: the new and old docblock sentences hit 0 files under dist/ and every other files[] path, while the positive controls MAJOR_18_CONVERSIONS and flowDecisionModeInclusiveExplicit hit dist/ chunks; registry.ts is not a src/**/*.zod.ts path.
  • No pin is owed: the change is a comment, and the rule it states is already pinned by the merge test above.
Derived gate families (dispatch-gates --commands at 6943445): 67 run, exit codes captured before any pipe

node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectstack --ran → "67 derived, 67 run, 0 NOT-MEASURED, 0 UNRUN" (a DERIVED zero: every line carries an exit code, none is 3).

# Command Exit
1 node scripts/check-adr-0087-registration.mjs --base origin/main 0
2 node scripts/check-adr-0087-registration.mjs --self-test 0
3 node scripts/check-closing-keyword-parity.mjs 0
4 node scripts/check-closing-keyword-parity.mjs --self-test 0
5 node scripts/check-comment-mask-adoption.mjs 0
6 node scripts/check-comment-mask-adoption.mjs --self-test 0
7 node scripts/check-comment-mask-corpus.mjs 0
8 node scripts/check-dev-prereqs.mjs --self-test 0
9 node scripts/check-dts-emitted.mjs --self-test 0
10 node scripts/check-issue-citations.mjs 0
11 node scripts/check-plugin-teardown-shape.mjs 0
12 node scripts/check-plugin-teardown-shape.mjs --self-test 0
13 node scripts/ci/assert-turbo-remote-cache.mjs --self-test 0
14 node scripts/ci/plan-test-core-shards.mjs --self-test 0
15 node scripts/ci/prune-turbo-cache.mjs --self-test 0
16 node scripts/docs-audit/check-affected-docs.mjs 0
17 node scripts/docs-audit/check-drift-comment.mjs 0
18 pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 (first run exit 3, PREREQUISITE NOT MET: other packages unbuilt; re-run 0 after the full turbo run build, 118/118 tasks)
19 pnpm --filter @objectstack/spec run check:api-surface 0
20 pnpm --filter @objectstack/spec run check:browser-reachable-entries 0
21 pnpm --filter @objectstack/spec run check:docs 0
22 pnpm --filter @objectstack/spec run check:dual-source-exports 0
23 pnpm --filter @objectstack/spec run check:duration-unit-keys 0
24 pnpm --filter @objectstack/spec run check:empty-state 0
25 pnpm --filter @objectstack/spec run check:entry-nameability 0
26 pnpm --filter @objectstack/spec run check:export-origins 0
27 pnpm --filter @objectstack/spec run check:exported-any 0
28 pnpm --filter @objectstack/spec run check:liveness 0
29 pnpm --filter @objectstack/spec run check:llms-txt 0
30 pnpm --filter @objectstack/spec run check:skill-refs 0
31 pnpm --filter @objectstack/spec run check:strictness-ledger 0
32 pnpm --filter @objectstack/spec run check:upgrade-guide 0
33 pnpm --filter @objectstack/spec run check:variant-docs 0
34 pnpm check:changeset-gate-self-tests 0
35 pnpm check:ci-filter-parity 0
36 pnpm check:closed-ceremony-text 0
37 pnpm check:cross-package-test-inputs 0
38 pnpm check:dispatcher-error-vocabulary 0
39 pnpm check:doc-authoring 0
40 pnpm check:driver-memory-census 0
41 pnpm check:dts-closure 0
42 pnpm check:dual-build-cjs-loads 0 (first run exit 3, PREREQUISITE NOT MET: other packages unbuilt; re-run 0 after the full turbo run build, 118/118 tasks)
43 pnpm check:gitlink-declared 0
44 pnpm check:issue-citations 0
45 pnpm check:keyed-text-bounds 0
46 pnpm check:lean-entry-closure 0 (first run exit 3, PREREQUISITE NOT MET: other packages unbuilt; re-run 0 after the full turbo run build, 118/118 tasks)
47 pnpm check:logger-receiver-detach 0
48 pnpm check:merge-driver 0
49 pnpm check:nul-bytes 0
50 pnpm check:org-identifier 0
51 pnpm check:page-declaration-shape 0
52 pnpm check:platform-object-tenancy-census 0
53 pnpm check:pm-prior-rulings 0
54 pnpm check:published-files 0
55 pnpm check:refd-timer-probe 0
56 pnpm check:registry-log-declared 0
57 pnpm check:rest-log-spy-declared 0
58 pnpm check:role-word 0
59 pnpm check:slot-lookup 0
60 pnpm check:sourcemap-no-sources-content 0
61 pnpm check:spec-docblock-symbol-anchors 0
62 pnpm check:spec-parsed-alias 0
63 pnpm check:system-context-census 0
64 pnpm check:test-source-alias 0
65 pnpm check:tier-file-adoption 0
66 pnpm check:undeclared-dep-imports 0
67 pnpm check:watch-hint-literal 0

Local-only families: pnpm check:dev-prereqs exit 0; pnpm check:skill-frame-freshness exit 0.

Outside the derivation, left to CI: the 51 artifact-roster families, the 11 wide-population families, the 4 workflow-valued families, the 5 path-scheduled CI jobs and the 5 type-check lanes the tool names.

Acceptance notes

🤖 Generated with Claude Code

https://claude.ai/code/session_01L6bhgVugtCCwBs98FeR27P

…the definition

Since the per-entry split, a conversion is defined in its own module under
`./entries/18/<id>.ts` and `registry.ts` only imports it. The docblock's
placement bullet still told an author to define the conversion above the
next entry's definition, directly above `OrderedConversion`. It now says
what `scripts/conversions-major18-merge.test.ts` enforces: the module named
for the `id`, and the import directly above the import of the entry that
follows in the list, or after every other `./entries/18/` import when it
sorts last.

Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L6bhgVugtCCwBs98FeR27P
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 5, 2026
@github-actions github-actions Bot added the size/s label Nov 5, 2026
@github-actions

github-actions Bot commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

⚠️ 1 changed file(s) yielded no anchor (packages/spec/src/conversions/registry.ts), so the pages documenting them are NOT COVERED by this run — this is not a clean bill of health for those files. Nothing else in this diff resolved to a documentable surface (no symbol, route or SDK anchor derived from 1 changed package(s)).

What this run could not see
  • 1 changed file(s) yielded no anchor (packages/spec/src/conversions/registry.ts) — pages documenting those are invisible to this run
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 170 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json 14c67d446e577926460f3ed893e44cc32cbecb12 → packageMentionDocs.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 6943445b89f637352585ead984a2fd63d4e4fe37
Local-runs: none
Scope: packages/spec/src/conversions/registry.ts + packages/spec/scripts/conversions-major18-merge.test.ts (the gate that enforces the rule), packages/spec/src/conversions/entries/18/*.ts (the 95 modules the docblock describes), .claude/skills/spec-property-retirement/SKILL.md on main after PR #30109 (the same steps, read for agreement), AGENTS.md Post-Task Checklist step 3, scripts/check-empty-changeset.mjs, packages/spec/package.json files[] and packages/spec/tsup.config.ts (read for ②)

Inputs: card #29994 (body; comments 6619509152, 6619532361, 6632322266, 6634099014, 6666793161, 6668036951), PR #30643 (body, file list, net diff against main at 778aedf666), the check-runs on the head read at 2026-11-05T20:14Z: 23 completed success (among them Check Changeset, Governed Surface Queue Guard, PR-body guards, Spec property liveness, Flag docs affected by code changes, Plan Test Core shards, every Lint · lane, Lint · PM dispatch-gates, Type Check · consumer gates, Type Check · debt ledger, Type Check · source gates, Dogfood Regression Gate), 14 skipped by path filter, 0 failed; 29 still in progress at read time (Build Core, Test Core 1–8 — which carry conversions-major18-merge.test.ts — Test UI 1–16, Type Check UI, Type Check · workspace, Build & E2E UI, Live E2E UI). This verdict reads the completed conclusions; a later failure among the in-progress runs is a new fact for the queue, not covered here

① Derived judgments

  • No code line of registry.ts changed — right. The net diff is 9+/5− lines and every changed line is a * line inside the one block comment that opens at L160 and closes at L189 on main (L193 on the head); nothing outside that comment is touched, so the comment-stripped bytes of the file equal main's. The imports (L24–135), OrderedConversion (L146–151), inApplicationOrder (L154–158), the 95 entries of MAJOR_18_CONVERSIONS (L194–296), CONVERSIONS_BY_MAJOR (L326–349) and ALL_CONVERSIONS (L355–358) are byte-identical to main.
  • Public surface: none — right. MAJOR_18_CONVERSIONS is a non-exported const; the exported CONVERSIONS_BY_MAJOR and ALL_CONVERSIONS and their docblocks are unchanged, so dist/*.d.ts, api-surface and every schema-derived generated artifact are unaffected.
  • Accept-set: unchanged — right. The docblock now states the rule conversions-major18-merge.test.ts already enforces (④); the test, the PLACED_BEFORE_THE_RULE exemption (46 names) and every other gate are untouched, so nothing becomes accepted or refused that was not before.
  • Fixes #29994 — right. The card's two deliverables are the SKILL.md steps (landed in PR docs(skills): point spec-property-retirement at the split conversions layout #30109, partial landing 6634099014) and this docblock (scope addition 6619532361); this PR closes the remainder.

② Semver level

  • skip-changeset (label on the PR; Check Changeset success) — right. AGENTS.md step 3 reserves the label for "a diff that publishes nothing from any released package". @objectstack/spec's files[] are dist, json-schema, liveness, prompts, llms.txt, README.md, src/**/*.zod.ts, CHANGELOG.md, api-surface, spec-changes.json, protocol-upgrade-guide.md. registry.ts is not a *.zod.ts; the docblock sits on a non-exported const, so no .d.ts carries it; tsup.config.ts sets no legalComments, so esbuild drops a /** */ block that carries no @license/@preserve (the file's @__PURE__ annotations are not in the hunk); the sourcemaps ship without sourcesContent (check:sourcemap-no-sources-content). The changed text reaches no published artifact, so there is nothing a changeset could describe.
  • scripts/check-empty-changeset.mjs: no .changeset/*.md is added, modified or deleted — both of its rules are vacuous here; green.
  • Clause-②: no, Metadata-protocol: none — right: nothing an author can write, and no export, changes.

③ Boundary flags

  • Dev flag (PR body; report 6668036951): the test anchors a last-sorting import after the last ./entries/18/ import, not on OrderedConversion. Confirmed. definitionsTail (test L149–154) returns the line after the last DEFINITION match (L62, which recognises ./entries/18/ID.js imports only), and placementFindings (L170–186) demands that the last entry's import have no ./entries/18/ import after it (the want === undefined arm, L182–183). OrderedConversion appears nowhere in the test. Today the last such import (L135) is also the last import of the file, two lines above OrderedConversion's docblock (L137), so both anchors coincide; the new sentence names the one the test reads. Answered.
  • open_questions: [] — none.
  • Dev deviations (the attribution HTML comment as the PR body's first line; the dispatch prompt's two-line footer): PR-body form only; PR-body guards success. Accepted.
  • Docs Drift Check comment 6668037579 ("1 changed file yielded no anchor"): a comment-only hunk in a file no docs page anchors; Flag docs affected by code changes success. No action.
  • The seat claim's ⛔ list (6666793161: no code line of registry.ts, no edit to the merge test, no .claude/**) held — the file list is registry.ts alone and ① shows no code line moved.
  • Triage 6619509152 ("no @objectstack/skills changeset applies") covered the skill half; the spec half is judged in ②.

④ Design judgment

packages/spec/src/conversions/registry.ts L181–189, read against packages/spec/scripts/conversions-major18-merge.test.ts on main (unchanged since PR #29993's split, d79eecfe5b), the 95 modules under src/conversions/entries/18/, and SKILL.md on main (28ce3d1bfa).

Each sentence against what enforces it:

  • "DEFINE it in a module of its own, ./entries/18/ID.ts, the file named for the conversion's id" — definitionsOf (L144–146) takes the id from the import path, MODULE_PATH (L64) resolves entries/18/${id}.ts, and definitionInModule (L157–161) requires id: 'ID' inside that file: the file name IS the id, and the test refuses any other. 95/95 modules on main have that shape (const IDENT: MetadataConversion = {, an id: equal to the file name, export { IDENT }; as the last line).
  • "exporting it by name (export { IDENTIFIER };)" — definitionInModule requires the module to end with exactly that statement; the form the docblock prints is the form the test accepts.
  • "A new file never conflicts" — test header L26–27; git conflicts only on edits to one path.
  • "IMPORT it directly above the import of the entry that follows it in this list, so the conversion imported next after it is that entry" — placementFindings L174–185: for a non-exempt entry at list index i, the next ./entries/18/ import after its own must be the entry at i+1. definitionSite (L204–210), which builds the accepted retirement, inserts at docStart of the successor's import — the same instruction. Walked by hand: a conversion sorting first (successor actionAriaRemoved, import L119); one between two exempt neighbours; one between a rule-placed predecessor and that predecessor's successor (the predecessor's next import becomes the new one, which is now the entry that follows it — the test's own neighbour case, L404–413); two successive last-sorting ones (the second goes after the first, which then precedes it in the list too). All accepted.
  • "One that sorts last is imported after every other ./entries/18/ import" — definitionsTail L149–154 and the want === undefined arm of L182–183. Holds (③).
  • "The imports stand where the definitions stood before the split" — the file's codemod note L20–23 and the test header L29–31.
  • "their end is one gap too: importing every new conversion there conflicts exactly as appending here did" — the lit control L442–446 (definitions-end-a × definitions-end-b must conflict) built by retireAtDefinitionsEnd L232–235.
  • The unchanged bullets still match: insert where the identifier sorts (sortFindings L164–167, the list-end control L436–440); order one more than the highest (NEXT_ORDER L313); equal order applies in id order (inApplicationOrder L154–158, applicationOrder L238–244, asserted L426). The closing pointer to the test is true: the test holds the sort rule and the placement rule for every entry outside the exemption.

Skill agreement: SKILL.md L176–177 (entries/TOMAJOR/ID.ts, 文件名即 id, 按名 export; registry.ts 加 import 与列表项) and L215–218 (18 步: 照其头注按标识符插入 { conversion, order }; import 插在后继条目的 import 正上方; 尾部追加被 merge 测试拒收) say what the docblock now says; no sentence of either contradicts the other. The skill's gloss "(头注的「定义」拆分后即 import)" explained the OLD bullet and is now redundant rather than wrong — .claude/**, outside this card's remaining surface; nothing owed here.

Break attempts — a literal follower of the docblock against the test:

  • S1 — should-fix, registry.ts L181–182. The docblock names the module ./entries/18/ID.ts and says "IMPORT it" but never says the import specifier is spelled ./entries/18/ID.js. DEFINITION (test L62) recognises only from './entries/18/ID.js'; an import spelled .ts is reported by placementFindings as "no import of IDENT from its module in the file" (L177) and fails L335–342 — and tsc refuses it first (allowImportingTsExtensions is set only in packages/spec/tsconfig.scripts.json, not for src). The 95 neighbouring imports show the spelling, so an author who copies a neighbour is safe; one clause ("imported as ./entries/18/ID.js") closes it for one who does not.
  • S2 — should-fix, registry.ts L181–183. "exporting it by name" is also satisfied, in TypeScript's vocabulary, by export const IDENTIFIER: MetadataConversion = {, which definitionInModule refuses: it wants a bare const IDENTIFIER: MetadataConversion = { with id then toMajor: 18 as the first two keys, and export { IDENTIFIER }; as the module's final line. The parenthetical prints the accepted form, so a literal follower passes; saying the export is a separate last statement, or "as every module under entries/18/ is written", stops the other reading before the test does.
  • No sentence of the new text is false of the test or of the tree; no must-fix.

Implemented-by: claude/issue-29994-conversions-placement-docblock
Reviewed-by: session_01L6bhgVugtCCwBs98FeR27P

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:spec#2 · os-sales · session_01L6bhgVugtCCwBs98FeR27P

维护者速读

  • 改了什么:packages/spec/src/conversions/registry.ts 里 MAJOR_18_CONVERSIONS 上方的注释改成拆分后的真实做法:新转换写在自己的模块 ./entries/18/<id>.ts 里,在 registry.ts 只加一行 import(放在列表里紧随它那条的 import 之上)和一行列表项。只改注释,没有代码变化。
  • 为什么改:PR refactor(spec): codemod split of conversions/registry.ts into per-entry modules (#29987) #29993 把转换拆成每条一个模块后,这段注释还在教人把定义写进 registry.ts,照做的人要么手改索引,要么把转换塞回已经清空的文件。技能文件那一半已由 PR docs(skills): point spec-property-retirement at the split conversions layout #30109 改好,这是剩下的一半。
  • 风险与回滚:只改一段注释,不进任何发布产物,所以不带 changeset(skip-changeset)。回滚即 revert 本 PR。
  • 先看:packages/spec/src/conversions/registry.ts L181-189 → 对照 packages/spec/scripts/conversions-major18-merge.test.ts 的 definitionInModule 与 placementFindings。
  • 两分钟验证:pnpm --filter @objectstack/spec exec vitest run scripts/conversions-major18-merge.test.ts,预期 12 条全过。
  • 需要你做的:无,席位落地。
  • 席位意见:接受。契约面达档复核 PASS(comment 6668217294,Head-sha 6943445b),没有 must-fix;两条 should-fix 是注释还可以再补的写法细节,不采纳,理由见第 5 项。

席位核对

ACCEPT · head 6943445b89f637352585ead984a2fd63d4e4fe37 · 2026-11-05T20:15Z

  1. 形态:draft,base main,正文 Fixes #29994,全文只有这一个闭合关键词。只改 1 个文件,在认领文件面内,而且只动注释块;导入、列表项、函数、合并测试、.claude/**、skills/**、docs/adr/**、AGENTS.md 都没碰。标签 skip-changeset。
  2. 前提实测:在 origin/main 上,PR refactor(spec): codemod split of conversions/registry.ts into per-entry modules (#29987) #29993(d79eecfe)已把每个转换拆到 src/conversions/entries/18/ 下的模块里,registry.ts 只 import 它们;注释还写着 “DEFINE it directly above the definition of the entry that follows it … directly above OrderedConversion”。合并测试的头注(L26-31)早已按拆分后的规则判。前提成立。
  3. 门禁 check-runs:
    • head 6943445b 上读到 24 success、14 skipped、0 failure,另有 28 条仍在跑(Build Core、Test Core 1-8、Test UI 1-16 等)。全部跑完且无红,才 pr_ready + automerge_enable。
    • 契约复核 6668217294 在 Served-tier: CONTRACT_REVIEW_TIER 下 PASS,Scope 覆盖 hits(registry.ts)以及合并测试、entries/18/ 的 95 个模块和 main 上的技能文件。
    • dev 本地 67 条派生门禁 --ran 0 NOT-MEASURED,只证本地子集;三条首轮 exit 3 是前置包没构建,全量构建后重跑都是 0。合并测试本地 12/12。
    • 注释改动不欠 pin,也没有消融可做。
  4. 席位自读(TIER_DEFAULT,hits 之外的部分):本 PR 没有 hits 之外的文件。席位读了 diff:14 行全在一个块注释里,另两条规则(按标识符排序插入、order 的取法)和冲突说明原样保留。
  5. 接受的偏差:
    • 复核 S1:注释没说 import 的说明符要写成 ./entries/18/<id>.js。不采纳:写成 .ts 时 tsc 先报错,合并测试也会报 “no import of IDENT from its module”,两处都当场指出,不会悄悄合进去。
    • 复核 S2:“exporting it by name” 也能读成 export const …,而测试要的是裸 const 加文件末尾的 export { … };。不采纳:注释括号里给出的正是被接受的写法,照着写就能过;写成别的形式,测试会当场拒绝。
    • 这两处都是注释还能写得更细,不是写错。为此挪 head 还要再复核一次,不划算。
    • 新注释把 “排在最后的那条” 锚在最后一个 ./entries/18/ import 之后,而不是 OrderedConversion 之上,这是跟着测试写的,复核已核对。
  6. 范围外去向和 Skills-docs::
    • 种类是 none,没有 (narrowing),不欠 Skills-docs: 行。
    • 复核提到技能文件 L176-177 里 “头注的「定义」拆分后即 import” 这句现在多余但没错,不在本卡文件面内,不立卡。
  7. 落地条款:check-governed-merges.mjs --pr 30643 已在本 head 读过:1 个路径 0 个命中 governed 登记,14 行(+9 / -5)≤ 3000,属于 Tier S;落地前再读一次。CI 全绿后经 relay pr_ready + automerge_enable,跟到 MERGED,同一动作里摘 pm:dispatched。

Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review November 5, 2026 20:27
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Nov 5, 2026
Merged via the queue into main with commit b8929f4 Nov 5, 2026
70 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-29994-conversions-placement-docblock branch November 5, 2026 20:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/s skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

1 participant